Telegram Group & Telegram Channel
😡 How to: не писать `__init__`

До Python 3.7, если вы хотели создать объект Coordinate(x=1, y=2), приходилось писать:
class Coordinate:
def __init__(self, x: int, y: int):
self.x = x
self.y = y


Это выглядело нормально. Но:
📍 если убрать класс из API — теряется типизация;
📍 если разрешить создавать объект без данных — получаем некорректные объекты;
📍 если задать поля по умолчанию — объект становится мутируемым;
📍 для валидации нужно усложнять структуру.

Главная проблема

__init__ запускает код при каждом создании объекта, что усложняет работу, особенно если нужны побочные действия (например, открытие файла).

Пример проблемного кода:
class FileReader:
def __init__(self, path: str):
self._fd = fileio.open(path)


Вроде удобно. Но:
📍 Вы не можете передать fd напрямую — нужно городить object.__new__.
📍 Тестировать сложно — надо мокать fileio.open.
📍 Если open становится async, вам уже не обойтись __init__.

Ключевая ошибка: связывать создание объекта с побочными эффектами (например, I/O) — это антипаттерн.

Современное решение

1⃣ Используйте @dataclass для объявления:
@dataclass
class FileReader:
_fd: int # или лучше: FileDescriptor


2⃣ Вынесите создание объекта в @classmethod:
from typing import Self

@dataclass
class FileReader:
_fd: int

@classmethod
def open(cls, path: str) -> Self:
return cls(fileio.open(path))


Теперь создавайте объект так: FileReader.open("file.txt"), а не через __init__.

Это решение поддерживает:
📍 чистую типизацию
📍 возможность перехода на async
📍 множественные фабрики (from_fd, from_buffer, from_resource, ...)

3⃣ Типизируйте примитивы через NewType:
from typing import NewType
FileDescriptor = NewType("FileDescriptor", int)


Используйте в классе:
@dataclass
class FileReader:
_fd: FileDescriptor

@classmethod
def open(cls, path: str) -> Self:
return cls(fileio.open(path)) # пусть возвращает FileDescriptor


Новая практика для классов в Python:
1. Используйте @dataclass.
2. Не пишите __init__ вручную.
3. Добавляйте @classmethod-фабрики (.open(), .from_config(), .from_env()).
4. Используйте NewType.

Это даёт чистый, тестируемый, удобный и расширяемый код.

Библиотека питониста #буст
Please open Telegram to view this post
VIEW IN TELEGRAM



tg-me.com/pyproglib/6772
Create:
Last Update:

😡 How to: не писать `__init__`

До Python 3.7, если вы хотели создать объект Coordinate(x=1, y=2), приходилось писать:

class Coordinate:
def __init__(self, x: int, y: int):
self.x = x
self.y = y


Это выглядело нормально. Но:
📍 если убрать класс из API — теряется типизация;
📍 если разрешить создавать объект без данных — получаем некорректные объекты;
📍 если задать поля по умолчанию — объект становится мутируемым;
📍 для валидации нужно усложнять структуру.

Главная проблема

__init__ запускает код при каждом создании объекта, что усложняет работу, особенно если нужны побочные действия (например, открытие файла).

Пример проблемного кода:
class FileReader:
def __init__(self, path: str):
self._fd = fileio.open(path)


Вроде удобно. Но:
📍 Вы не можете передать fd напрямую — нужно городить object.__new__.
📍 Тестировать сложно — надо мокать fileio.open.
📍 Если open становится async, вам уже не обойтись __init__.

Ключевая ошибка: связывать создание объекта с побочными эффектами (например, I/O) — это антипаттерн.

Современное решение

1⃣ Используйте @dataclass для объявления:
@dataclass
class FileReader:
_fd: int # или лучше: FileDescriptor


2⃣ Вынесите создание объекта в @classmethod:
from typing import Self

@dataclass
class FileReader:
_fd: int

@classmethod
def open(cls, path: str) -> Self:
return cls(fileio.open(path))


Теперь создавайте объект так: FileReader.open("file.txt"), а не через __init__.

Это решение поддерживает:
📍 чистую типизацию
📍 возможность перехода на async
📍 множественные фабрики (from_fd, from_buffer, from_resource, ...)

3⃣ Типизируйте примитивы через NewType:
from typing import NewType
FileDescriptor = NewType("FileDescriptor", int)


Используйте в классе:
@dataclass
class FileReader:
_fd: FileDescriptor

@classmethod
def open(cls, path: str) -> Self:
return cls(fileio.open(path)) # пусть возвращает FileDescriptor


Новая практика для классов в Python:
1. Используйте @dataclass.
2. Не пишите __init__ вручную.
3. Добавляйте @classmethod-фабрики (.open(), .from_config(), .from_env()).
4. Используйте NewType.

Это даёт чистый, тестируемый, удобный и расширяемый код.

Библиотека питониста #буст

BY Библиотека питониста | Python, Django, Flask




Share with your friend now:
tg-me.com/pyproglib/6772

View MORE
Open in Telegram


Библиотека питониста | Python Django Flask Telegram | DID YOU KNOW?

Date: |

The global forecast for the Asian markets is murky following recent volatility, with crude oil prices providing support in what has been an otherwise tough month. The European markets were down and the U.S. bourses were mixed and flat and the Asian markets figure to split the difference.The TSE finished modestly lower on Friday following losses from the financial shares and property stocks.For the day, the index sank 15.09 points or 0.49 percent to finish at 3,061.35 after trading between 3,057.84 and 3,089.78. Volume was 1.39 billion shares worth 1.30 billion Singapore dollars. There were 285 decliners and 184 gainers.

A Telegram spokesman declined to comment on the bond issue or the amount of the debt the company has due. The spokesman said Telegram’s equipment and bandwidth costs are growing because it has consistently posted more than 40% year-to-year growth in users.

Библиотека питониста | Python Django Flask from cn


Telegram Библиотека питониста | Python, Django, Flask
FROM USA